#include <stdint.h>
#include "UnitTest++.h"
#include "handshake.h"
#include "tropicssl/rsa.h"

struct HandshakeFixture
{
  static const uint8_t nonce[41];
  static const uint8_t id[13];
  static const uint8_t pubkey[295];
  static const uint8_t private_key[613];
  static const uint8_t encrypted_aes_credentials[129];
  static const uint8_t expected_hmac[21];
  static const uint8_t signature[257];
};

const uint8_t HandshakeFixture::nonce[41] =
  "\x5D\x60\x41\xD1\x67\xBF\x18\xAF\x1D\xDA\xA4\x7C\x18\x83\x92\xA1"
  "\x04\xDE\xB0\xFF\xB9\x92\x2A\x12\xA6\x28\x9C\x60\x3E\x4F\xEB\x35"
  "\x8C\x18\xF9\xA1\x8A\x61\x0D\xA4";

const uint8_t HandshakeFixture::id[13] =
  "\x1A\x11\x8A\xD1\xC8\x86\xD5\x42\x40\xCE\x4B\x17";

const uint8_t HandshakeFixture::pubkey[295] =
  "\x30\x82\x01\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01"
  "\x01\x05\x00\x03\x82\x01\x0F\x00\x30\x82\x01\x0A\x02\x82\x01\x01"
  "\x00\xBB\xA0\x8A\x8D\xA3\xC5\x50\x2A\x8D\x7D\xE6\x0B\x6E\x39\x37"
  "\x14\xF5\x4A\xE2\xE7\xA3\x65\x2E\x50\x18\x4D\xB8\x2E\x83\x87\x9C"
  "\xEC\x4F\xF4\x48\xBD\x22\x85\x15\xD8\x77\xDD\xFB\x98\x69\xB4\x77"
  "\xF5\xEE\x37\xFB\xFF\xA4\xAE\x58\x3D\x05\x6F\x04\x43\xFA\x4F\x29"
  "\x7A\x56\x8A\x01\xEC\xF2\xAC\xB8\xAC\x8A\x9F\x7C\x31\xA3\xC0\xF2"
  "\xB2\x48\xF1\xF0\x7E\xB0\x5B\x20\x33\x34\x3C\x98\xAE\xE7\xC6\x8E"
  "\x13\xBC\x1D\x3A\x9E\xA2\x68\x8E\x7B\x9D\x12\x70\x4C\x5A\xE3\xDE"
  "\x8E\xD6\xE2\xFC\xA3\xDA\x36\xEF\xEA\x5F\x3E\xBF\xC5\x87\x3D\x93"
  "\x23\xC9\xB9\x2F\x4D\x67\xFB\x3F\xAF\x87\x85\xC9\x45\x2C\x25\x84"
  "\x82\x03\x38\x5D\x2E\x7B\x8A\x75\xFD\xB1\x8C\xE7\x18\xE3\x71\x06"
  "\x0A\x96\xD8\x81\xB0\xAB\x21\x31\x9B\x3A\x26\x08\xE2\xE8\x24\xC4"
  "\xD8\x88\x41\xE9\x17\x84\x52\x63\x06\x48\xD6\x89\xDE\xB5\x08\xDA"
  "\x2E\x61\x71\x87\xBA\x26\x2F\xE0\x02\x5A\x85\x97\x33\x27\x62\xA5"
  "\x39\x9C\xF4\x82\xFA\xEF\x9A\x4A\x97\xC0\x3D\x3A\xFF\xAE\x1B\x8D"
  "\xE5\x5E\x6B\xDB\x7F\x77\xFB\x0C\xB4\x80\x54\x80\x44\x49\xE2\x3B"
  "\x2D\x1E\x23\x2E\x68\x4F\xDA\xD6\xB0\xC8\xDA\x2D\x37\xDF\x4A\x00"
  "\x8B\x02\x03\x01\x00\x01";

const uint8_t HandshakeFixture::private_key[613] =
  "\x30\x82\x02\x5B\x02\x01\x00\x02\x81\x81\x00\xA8\x7C\xF2\xB1\x66"
  "\x0B\x5B\xFB\xD9\x7D\x62\x3A\xA0\x06\x75\xC1\xD4\x12\x2F\x67\xF9"
  "\xC3\x10\x87\x9F\xC7\x9B\x91\x70\xE5\x46\x8E\x27\x53\x06\x80\xCC"
  "\x09\xEE\x77\x77\x7F\x55\xEC\xAB\xAF\x63\xD7\xBD\xD8\x0B\x4D\x04"
  "\x01\xB9\x0D\xDD\x0D\x87\x25\x5A\x12\x39\x54\x90\x81\xCE\x07\x3B"
  "\xDC\x47\x01\xA6\xE6\xD9\x54\xCE\x71\xA5\xBD\x53\x48\x1E\xB4\x10"
  "\xEC\x6A\xBE\x94\xF0\xCD\x28\xD5\x76\x06\x0F\x02\x80\x11\x16\x8F"
  "\xEF\xBB\x4C\xFA\xDA\xA8\x48\x24\x64\xD1\xA1\x92\x2F\xB9\x4D\xE4"
  "\x32\x38\xD2\x5C\xE2\x30\xC1\x5E\xDB\xD8\xA1\x02\x03\x01\x00\x01"
  "\x02\x81\x80\x14\xE2\xC8\x42\xED\x5F\x63\x1B\xA9\x2E\x3D\xCA\xFE"
  "\xA3\x4E\x5D\xA4\xA8\x4C\x70\x1B\x29\xEF\x16\xA0\xDB\xE1\x90\xF9"
  "\xE9\xB2\x01\x55\x26\x99\x9B\xC5\xAF\x45\x7C\x51\xB7\xDB\x32\xE7"
  "\x65\x6A\x7F\x07\xED\x8C\x19\x13\xF2\x12\xBA\x81\x38\x78\x14\x4D"
  "\x42\x0D\x11\x16\xF7\xD5\xAA\xFB\x4C\x24\xE8\x56\xD8\xCB\x25\x37"
  "\xEC\x3D\x20\xF3\xCE\xDA\x09\xDC\x8C\xC0\x30\x35\xC7\x3F\xFA\x2C"
  "\x9A\x46\x6D\xED\x82\x3D\x08\xC7\xD7\x06\xD1\x9C\x7F\x5A\x91\x24"
  "\x23\x7B\x9A\xEA\x12\x5D\xC0\x4B\x2A\xCC\x5E\xB9\x0C\x4D\xBD\x75"
  "\x1E\x5C\xF1\x02\x41\x00\xDB\x45\x35\x37\xCB\x27\x56\x5A\xA8\x1D"
  "\x3D\x4A\x28\xB9\xF7\xD3\x10\xDF\x14\x47\x5F\x2E\x13\xC5\x02\x35"
  "\x14\x0D\xFC\x89\xFE\xE5\x85\xDB\x65\x42\x15\x2B\xA2\xF4\x6E\x3B"
  "\x78\xBF\xC6\xAC\x9D\x52\xC0\x28\x27\xE8\x5C\xC8\x91\x50\xD1\x61"
  "\xA6\x19\x59\xF0\xFB\x07\x02\x41\x00\xC4\xB6\x15\xE2\xB1\xE6\x78"
  "\x43\x4C\xE6\x89\x93\x4F\x94\xFB\xC6\x2E\x3F\xC3\xF1\x36\xA3\xD8"
  "\xC5\xB4\xC8\x65\xFE\xD8\xC8\x22\xA2\x3D\xBD\xAC\x9E\x00\x00\xC4"
  "\x00\x36\x60\x31\x27\xDA\xFD\x69\x6C\x83\xB6\xE7\x67\x03\x38\x01"
  "\xB5\x0D\x9C\xD0\x6E\x33\x2E\x9D\x17\x02\x40\x71\xE1\x16\xCB\x9C"
  "\x5A\x18\xD2\x4A\x9F\xAC\xF6\x38\x02\xA5\xC0\x5B\xF1\xD0\x01\x65"
  "\x60\x73\xEA\x0C\xC4\x6E\x5E\xF9\x3A\xDE\x44\x6C\x69\xCE\xC4\x2C"
  "\x64\x96\x64\x66\x5F\xC2\xCD\xAF\x2C\x75\x24\xC6\x21\xD4\xE0\x2C"
  "\x58\x0A\x88\xB3\xC6\x08\x53\x00\x50\x54\xBF\x02\x40\x72\x94\x95"
  "\x7E\xEC\x9D\x10\x64\x33\x40\xFD\xD5\xDE\xBF\x2B\x40\xAE\xE3\xD9"
  "\xA0\x81\x71\x42\xED\x36\x76\x9C\x62\xAB\xA7\x37\xF5\x44\xFD\x5C"
  "\xB4\xD3\xCF\x9E\x5B\x79\x50\xE2\x91\x12\x90\x15\x7E\x6D\xE2\x76"
  "\x3B\x9C\xB6\x5C\xD8\x37\x4B\xA6\x64\xEA\x4F\x36\x95\x02\x40\x07"
  "\xFE\xA4\xF4\xB7\xF4\xD6\x6F\x45\xE5\xA9\x52\xC6\xD2\xDD\x6B\x0C"
  "\xA2\x48\x36\x22\x33\x37\x1B\xE3\x05\xA0\x2F\xDC\xD9\xB3\xDB\x91"
  "\x6D\xDA\xB3\x6A\xD6\x68\x16\x08\x13\xC3\xBE\xE0\x68\xC5\xBF\x8E"
  "\xC0\x27\x20\x63\xF6\xAF\x95\x48\x73\x74\x57\x8F\x40\x3F\x80\x00"
  "\x00\x00\x00\x00";

const uint8_t HandshakeFixture::encrypted_aes_credentials[129] =
  "\x3C\xB1\x5F\x90\xC9\xAE\xFB\xDC\xF0\x44\xB3\x63\x03\x55\x9E\x67"
  "\x2A\xC0\xFE\x90\x1A\x8A\xB9\xE1\x16\xFB\x90\x8D\x3C\x8C\x29\xB5"
  "\x3D\xE2\xA2\x89\x4B\x60\xCF\x2D\x72\xD8\xFF\xEC\x9B\x91\x6C\x86"
  "\x34\x9B\x3C\xE1\xEA\xE4\x43\x40\x17\x8A\x0A\x00\x9A\xC0\x7F\x32"
  "\xE5\x65\x56\xA5\xA8\x36\xC1\x86\xD8\x05\x77\x01\xBF\xB6\x6D\x29"
  "\x33\xE4\x6D\xD0\x3C\xA0\x3A\xD4\xCB\xEA\x4A\xAD\x66\x96\x05\x41"
  "\x91\x07\xFE\x8A\x65\x6F\xBA\xC7\xFA\x73\xA3\x40\x91\xBC\x18\xF6"
  "\x5C\x9E\x4B\xD3\x64\x76\xD8\x4E\x6D\xFB\x57\x1E\x54\x14\x51\x52";

const uint8_t HandshakeFixture::expected_hmac[21] =
  "\x34\xA4\x7A\x49\xB4\xF4\xBE\xD3\x74\x95\xA5\xFC\x0B\x3E\x0F\x41"
  "\x4A\xE6\xB9\x2B";

const uint8_t HandshakeFixture::signature[257] =
  "\x13\xA4\x31\x5A\x28\x18\x89\x6A\xB9\xF3\xC1\xB9\x29\x33\xC5\x93"
  "\x14\xD7\x96\xAA\x38\x2A\xC1\x12\xE8\x67\xE9\x94\x56\xD1\xCC\x16"
  "\xA4\xA4\x4B\xD2\x01\xA8\xC5\x52\x5B\xAF\x8D\x38\x67\xC6\x0D\x3A"
  "\x21\xEC\x14\xCA\x91\x29\x33\xD1\xBC\x9F\x41\x05\xE1\xB0\x2B\xB6"
  "\x16\x55\xBA\xBC\x7D\x71\x5B\xE9\xCB\xE6\xF1\x30\x5E\x99\x64\x76"
  "\x8D\x76\x21\xD1\x5B\xA1\x03\xCA\xF6\xEA\x71\x5C\x1D\x3D\xAA\x54"
  "\x38\x44\xE7\xC9\x5C\x82\xE3\xB0\x18\xF6\x49\xBC\x91\x09\x36\x4B"
  "\x0F\x06\xAD\xB8\x42\x28\x21\x3C\x30\x26\x42\x3F\x1A\x43\x7D\x85"
  "\xFB\x40\x4D\x95\xDF\x50\xCD\x73\x97\x28\x71\xD1\xF9\x7E\xD1\xB1"
  "\xF5\xAA\x5E\x4D\xB7\x4F\xB4\xD5\x75\x62\x8D\xA2\x0F\x69\x7A\x3B"
  "\xA9\x04\x8C\xB9\xF1\xC2\xA7\x33\x92\xBA\x53\x9C\x0F\x5C\x10\x40"
  "\x49\x99\xA8\x03\xB2\x12\xAD\x28\xEE\xF0\x64\x86\xB9\x40\x8B\xB9"
  "\x97\x45\xB2\x1D\x89\x3C\x2A\xE9\x39\x75\x88\x11\x7B\x6D\x8F\xE9"
  "\x90\x30\x5D\x73\x21\xB6\xBC\xFD\x5B\xA7\x2F\xEB\x4B\x18\x88\x13"
  "\x6A\xBE\x0B\xC6\xA5\xC6\xDA\xC7\xC8\x7E\x01\x48\xFA\xFF\x52\xD7"
  "\xCB\x1B\x64\x52\x61\x01\x14\x31\x2D\x57\x2B\x1B\xEE\xA4\x65\x70";

TEST_FIXTURE(HandshakeFixture, NoErrorsGeneratingCiphertext)
{
  uint8_t ciphertext[256];
  int err = ciphertext_from_nonce_and_id(nonce, id, pubkey, ciphertext);
  CHECK_EQUAL(0, err);
}

TEST(RSASelfTestSucceeds)
{
  CHECK_EQUAL(0, rsa_self_test(0));
}

TEST(MPISelfTestSucceeds)
{
  CHECK_EQUAL(0, mpi_self_test(0));
}

TEST(SHA1SelfTestSucceeds)
{
  CHECK_EQUAL(0, sha1_self_test(0));
}

TEST_FIXTURE(HandshakeFixture, FixturePublicKeyIsValid)
{
  rsa_context rsa;
  init_rsa_context_with_public_key(&rsa, pubkey);
  CHECK_EQUAL(0, rsa_check_pubkey(&rsa));
}

TEST_FIXTURE(HandshakeFixture, FixturePrivateKeyIsValid)
{
  rsa_context rsa;
  init_rsa_context_with_private_key(&rsa, private_key);
  CHECK_EQUAL(0, rsa_check_privkey(&rsa));
}

TEST_FIXTURE(HandshakeFixture, NoErrorsInRSADecryption)
{
  uint8_t aes_credentials[40];
  int err = decipher_aes_credentials(private_key,
                                     encrypted_aes_credentials,
                                     aes_credentials);
  CHECK_EQUAL(0, err);
}

TEST_FIXTURE(HandshakeFixture, RSADecryptionMatchesOpenSSLExample)
{
  uint8_t expected[41] =
    "\x3E\x78\xEB\x7A\x0B\xB2\x1D\xFB\xF2\xB1\x53\x4B\x06\xE5\x66\x12"
    "\x14\x5A\x01\xF1\x07\x0E\x40\xA1\x11\x88\xF7\x84\xC4\x9B\xC6\x53"
    "\xC5\x76\x94\xFC\x1F\x3B\x7D\x72";
  uint8_t aes_credentials[40];
  decipher_aes_credentials(private_key,
                           encrypted_aes_credentials,
                           aes_credentials);
  CHECK_ARRAY_EQUAL(expected, aes_credentials, 40);
}

TEST_FIXTURE(HandshakeFixture, HMACMatchesOpenSSLExample)
{
  uint8_t hmac[20];
  uint8_t hmac_key[40];
  decipher_aes_credentials(private_key,
                           encrypted_aes_credentials,
                           hmac_key);
  calculate_ciphertext_hmac(encrypted_aes_credentials, hmac_key, hmac);
  CHECK_ARRAY_EQUAL(expected_hmac, hmac, 20);
}

TEST_FIXTURE(HandshakeFixture, VerifiedSignatureIsHMAC)
{
  int err = verify_signature(signature, pubkey, expected_hmac);
  CHECK_EQUAL(0, err);
}
